#include <iostream>
#include <queue>
#include <fstream>
#include <sstream>
#include <vector>
#include <SDL/SDL.h>
#include <cmath>
#include <ctime>


#include "nucleo.h"
#include "evento.h"
#include "Personajes.h"
#include "Tecnologias.h"
#include "mapa.h"
#include "sred.h"


#define PATRIOTAS 0
#define INVASORES 1
#define MAXMAP 1000
#define MAXPUNT 10000
#define NMAPAS 9

using namespace std;


c_nucleo::c_nucleo()
{
 ejercito=-1;
 c_evento ev(E_TERMINARCICLO);
 eventos.push(ev);

     //Se inicializan las estructuras de datos
     cargar_patriotas();
     cargar_invasores();
     cargar_tecnologias();
     cargar_jugador();
     cargar_info_unidades();
     cargar_info_tecnologias();
     carga_mapas();
     
     puntos_cliente=-1;



}

c_nucleo::~c_nucleo()
{
 SDL_Quit(); 
}

void c_nucleo::cargar_patriotas(){
     
int num_total;
personaje p;
ifstream datos("./config/patriotas");
string bufer; // Para leer cada linea

datos >> num_total;

getline(datos,bufer); // para desechar la primera linea

for(int i=0;i<num_total;i++){

getline(datos,bufer);
//Creamos un flujo en memoria sobre bufer
istringstream linea(bufer);
//Se leen los componentes de la linea y se van almacenando en la ED 
linea >> p.id >> p.im1 >> p.im2 >> p.im3 >> p.nombre >> p.coste >> p.ataque_esp >> p.alcance_ataque >> p.danio_ataque >> p.blindaje >> p.mov >> p.vida >> p.sonido1 >> p.sonido2 >> p.sonido3 >> p.im_presentacion >>p.num_desc >> p.tecnologia >> p.evolucion >> p.comprar;     
//Se leen las lineas de descripciones
p.desc=new string[p.num_desc];
for(int i=0;i<p.num_desc;i++){
getline(datos,p.desc[i]);    
}
p.experiencia=0;
patriotas.push_back(p);

}
}

void c_nucleo::cargar_invasores(){
     
int num_total;
personaje p;
ifstream datos("./config/invasores");
string bufer; // Para leer cada linea

datos >> num_total;

getline(datos,bufer); // para desechar la primera linea

for(int i=0;i<num_total;i++){

getline(datos,bufer);
//Creamos un flujo en memoria sobre bufer
istringstream linea(bufer);
//Se leen los componentes de la linea y se van almacenando en la ED 
linea >> p.id >> p.im1 >> p.im2 >> p.im3 >> p.nombre >> p.coste >> p.ataque_esp >> p.alcance_ataque >> p.danio_ataque >> p.blindaje >> p.mov >> p.vida >> p.sonido1 >> p.sonido2 >> p.sonido3 >> p.im_presentacion >>p.num_desc >> p.tecnologia >> p.evolucion >> p.comprar;    
//Se leen las lineas de descripciones
p.desc=new string[p.num_desc];
for(int i=0;i<p.num_desc;i++){
getline(datos,p.desc[i]);    
}
p.experiencia=0;
invasores.push_back(p);


}
}



void c_nucleo::cargar_tecnologias(){
     
ifstream datosp("./config/tecnologias_pat");
ifstream datosi("./config/tecnologias_inv");
int num_total;
string bufer; // Para leer cada linea
tecnologias t;

datosp >> num_total;

getline(datosp,bufer); // para desechar la primera linea

for(int i=0;i<num_total;i++){

getline(datosp,bufer);
//Creamos un flujo en memoria sobre bufer
istringstream linea(bufer);
//Se leen los componentes de la linea y se van almacenando en la ED 
linea >> t.num_tecnologia >> t.num_desc >> t.nombre >> t.coste >>t.comprar >> t.tec_ev >> t.nivel_ev;     
//Se leen las lineas de descripciones
t.desc=new string[t.num_desc];
for(int j=0;j<t.num_desc;j++){
getline(datosp,t.desc[j]);    
}
tecs_pat.push_back(t);
}

datosi >> num_total;

getline(datosi,bufer); // para desechar la primera linea

for(int i=0;i<num_total;i++){

getline(datosi,bufer);
//Creamos un flujo en memoria sobre bufer
istringstream linea(bufer);
//Se leen los componentes de la linea y se van almacenando en la ED 
linea >> t.num_tecnologia >> t.num_desc >> t.nombre >> t.coste >>t.comprar >> t.tec_ev >> t.nivel_ev;     
//Se leen las lineas de descripciones
t.desc=new string[t.num_desc];
for(int j=0;j<t.num_desc;j++){
getline(datosi,t.desc[j]);    
}
tecs_inv.push_back(t);
}

}

void c_nucleo::cargar_jugador(){

ifstream datos("./config/jugador.save");
string bufer;
     
getline(datos,bufer);
//Creamos un flujo en memoria sobre bufer
istringstream linea(bufer);
//Se leen los componentes de la linea y se van almacenando en la ED 
linea >> j.nombre >> j.dinero;

}
     

void c_nucleo::cargar_info_unidades()
{
     ifstream datosp("./config/patriotas.save");
     ifstream datosi("./config/invasores.save");
     int num_pat,num_inv,num_unidad,exp;
     string bufer;
     personaje p;
     
     datosp >> num_pat;
     getline(datosp,bufer);
     
     for(int i=0;i<num_pat;i++){
             getline(datosp,bufer);
             istringstream linea(bufer);
             linea >> num_unidad >> exp;
             p=patriotas[num_unidad];
             p.experiencia=exp;
             j.unidades_pat.push_back(p);
             }
     
     
     
     datosi >> num_inv;
     getline(datosi,bufer);
     
     for(int k=0;k<num_pat;k++){
             getline(datosi,bufer);
             istringstream linea(bufer);
             linea >> num_unidad >> exp;
             p=invasores[num_unidad];
             p.experiencia=exp;
             j.unidades_inv.push_back(p);
             }     
             
}

void c_nucleo::cargar_info_tecnologias()
{
     ifstream datosp("./config/tecnologias_pat.save");
     ifstream datosi("./config/tecnologias_inv.save");
     int num_total,num_tec,nivel;
     string bufer;
     tecnologias t;
     
     datosp >> num_total;
     getline(datosp,bufer);
     
     for(int i=0;i<num_total;i++){
             getline(datosp,bufer);
             istringstream linea(bufer);
             linea >> num_tec >> nivel;
             t=tecs_pat[num_tec];
             t.nivel=nivel;
             j.tecs_pat.push_back(t);
             }
             
     datosi >> num_total;
     getline(datosi,bufer);
     
     for(int i=0;i<num_total;i++){
             getline(datosi,bufer);
             istringstream linea(bufer);
             linea >> num_tec >> nivel;
             t=tecs_inv[num_tec];
             t.nivel=nivel;
             j.tecs_inv.push_back(t);
             }
     
             
}


vector<personaje> c_nucleo::unidades_disponibles()
{
                  vector<personaje> disp;
       
       for(unsigned int i=0;i<patriotas.size();i++){
               if(patriotas[i].coste<j.dinero && patriotas[i].comprar == true)
                                               disp.push_back(patriotas[i]);
                                               
                                               }

       for(unsigned int i=0;i<invasores.size();i++){
               if(invasores[i].coste<j.dinero && invasores[i].comprar == true)
                                               disp.push_back(invasores[i]);
                                               
                                               }

               return disp;
               
               }

vector<tecnologias> c_nucleo::tecnologias_disponibles()
{
                  vector<tecnologias> disp;
       
       for(unsigned int i=0;i<tecs_pat.size();i++){
               if(tecs_pat[i].coste<j.dinero && tecs_pat[i].comprar == true)
                                               disp.push_back(tecs_pat[i]);
                                               
                                               }
       for(unsigned int i=0;i<tecs_inv.size();i++){
               if(tecs_inv[i].coste<j.dinero && tecs_inv[i].comprar == true)
                                               disp.push_back(tecs_inv[i]);
                                               
                                               }

               return disp;
               
               }

void c_nucleo::comprar_unidad(int ejercito,int num_unidad){
// ejercito=0 ->patriotas  ejercito=1 -> invasores     
     personaje unidad,aux;
     int ev,posicion;

     if(ejercito == PATRIOTAS){
         unidad=patriotas[num_unidad];
          if((ev=unidad.evolucion) != -1){
              posicion=devuelve_ud(unidad.evolucion,j.unidades_pat);//Elimino la unidad desde la que evoluciono                   
              aux=j.unidades_pat[j.unidades_pat.size()-1];
              j.unidades_pat[posicion]=aux;
              j.unidades_pat.pop_back();           
                                 }
         j.unidades_pat.push_back(unidad);
         } //Se añade la unidad a la estructura del jugador
     else{
         unidad=invasores[num_unidad];
         if((ev=unidad.evolucion) != -1){
              posicion=devuelve_ud(unidad.evolucion,j.unidades_inv);//Elimino la unidad desde la que 			                                                      evoluciono                   
              aux=j.unidades_inv[j.unidades_pat.size()-1];
              j.unidades_pat[posicion]=aux;
              j.unidades_pat.pop_back();           
                                 }
         j.unidades_inv.push_back(unidad); //Se añade la unidad a la estructura del jugador

}
j.dinero-=unidad.coste;

}

void c_nucleo::comprar_tecnologia(int ejercito,int num_tec){
// ejercito=0 ->patriotas  ejercito=1 -> invasores     

vector<tecnologias> tecs;
tecnologias t;
bool disponible=false;
    
    switch(ejercito){
                     case PATRIOTAS: tecs=j.tecs_pat;
                                     t=tecs_pat[num_tec];
                                     break;
                     case INVASORES: tecs=j.tecs_inv;
                                     t=tecs_inv[num_tec];
                                     break;
                                     }
    
    
    
           for(unsigned int i=0;i<tecs.size();i++){
             if(tecs[i].num_tecnologia == num_tec){
                if(ejercito == PATRIOTAS){
                            j.tecs_pat[i].nivel++;}
                            else{
                                 j.tecs_inv[i].nivel++;
                                 }
                                 disponible=true;
                                 }
                                 }
             
             if(disponible == false){
                 if(ejercito== PATRIOTAS){
                    t.nivel=1;           
                    j.tecs_pat.push_back(t);
                    }
                    else{
                    t.nivel=1;
                    j.tecs_inv.push_back(t);
                    }
                    }
                    
j.dinero-=t.coste;

}

void c_nucleo::volcado_memoria_a_ficheros()
{
//Volcado de patriotas.save
ofstream pat("./config/patriotas.save");

pat << j.unidades_pat.size();

for(unsigned int i=0;i<j.unidades_pat.size();i++){
   pat << '\n' << j.unidades_pat[i].id << ' ' << j.unidades_pat[i].experiencia;
       }

//Volcado de invasores.save
ofstream inv("./config/invasores.save");

inv << j.unidades_inv.size();

for(unsigned int i=0;i<j.unidades_inv.size();i++){
   inv << '\n' << j.unidades_inv[i].id << ' ' << j.unidades_inv[i].experiencia;
       }
       
//Volcado de tecnologias_pat.save
ofstream tec_pat("./config/tecnologias_pat.save");

tec_pat << j.tecs_pat.size();

for(unsigned int i=0;i<j.tecs_pat.size();i++){
   tec_pat << '\n' << j.tecs_pat[i].num_tecnologia << ' ' << j.tecs_pat[i].nivel;
       }

//Volcado de tecnologias_inv.save
ofstream tec_inv("./config/tecnologias_inv.save");

tec_inv << j.tecs_inv.size();

for(unsigned int i=0;i<j.tecs_inv.size();i++){
   tec_inv << '\n' << j.tecs_inv[i].num_tecnologia << ' ' << j.tecs_inv[i].nivel;
       }

//Volcado de jugador.save
ofstream jug("./config/jugador.save");

jug << j.nombre << ' ' << j.dinero;

}

vector<int> c_nucleo::nuevas_tecs(int ejercito){
          //Devuelve los indices de las tecnologías de nueva adquisición

vector<int> res;
vector<tecnologias> tecs,tecs_jug;

                    switch(ejercito){
                                     case PATRIOTAS: tecs=tecs_pat;
                                                     tecs_jug=j.tecs_pat;
                                                     break;
                                     case INVASORES: tecs=tecs_inv;
                                                     tecs_jug=j.tecs_inv;
                                                     break;
                                                     }
                                                     


      for(unsigned int i=0;i<tecs.size();i++){

              if(tec_en_vector(tecs[i].num_tecnologia,tecs_jug) && (tecs_jug[devuelve_tec(i,tecs_jug)].coste)*(int)(pow((double)2,(double)(tecs_jug[devuelve_tec(i,tecs_jug)].nivel))) <= j.dinero){
                 res.push_back(tecs[i].num_tecnologia);
                 }
                 if(tec_en_vector(tecs[i].tec_ev,tecs_jug) && tecs_jug[devuelve_tec(tecs[i].tec_ev,tecs_jug)].nivel >= tecs[i].nivel_ev && !tec_en_vector(i,tecs_jug)){
                         res.push_back(tecs[i].num_tecnologia);
                         
                         }
}

return res;
}

int c_nucleo::tec_en_vector(int tec,vector<tecnologias> tecs_jug){
    
    for(unsigned int i=0;i<tecs_jug.size();i++){
            if(tecs_jug[i].num_tecnologia == tec)
                                          return true;
                                          }
            return false;
                                          
                                          }

int c_nucleo::devuelve_tec(int tec,vector<tecnologias> tecs_jug){
    bool encontrado=false;
    for(unsigned int i=0;i<tecs_jug.size();i++){
            if(tecs_jug[i].num_tecnologia == tec){
                                          return i;
                                          encontrado=true;
                                          }
                                          }
            if(encontrado == false){
                          return -1;
                          }
                          return -1;
                          }



bool c_nucleo::muerto(personaje p){
     if(p.vida <= 0) return true;
     else return false;
     
     }    



vector<tecnologias> c_nucleo::tecs(int ejercito){
                    switch(ejercito){
                                     case PATRIOTAS: return tecs_pat;
                                                     break;
                                     case INVASORES: return tecs_inv;
                                                     break;
                                                     }
                                                     return tecs_pat;
                                                     }


int c_nucleo::nivel_tec(int ejercito, int tecnologia){
     vector<tecnologias> tecs;
     
                        switch(ejercito){
                                         case PATRIOTAS: tecs=j.tecs_pat;
                                                         break;
                                         case INVASORES: tecs=j.tecs_inv;
                                                         break;
                                                         }
                                                         
      for(unsigned int i=0;i<tecs.size();i++){
              if(tecs[i].num_tecnologia == tecnologia)
                         return tecs[i].nivel;
                         }
                        return 0;
                        
                         }
                         

int c_nucleo::dinero(){
    return j.dinero;
}


                  
int min_aux(int a,int b){
    if(a<b) return a;
    else return b;
}

int min(int a,int b,int c){
    int aux;
    
    aux=min_aux(a,b);
    return min_aux(aux,c);
}

                  


void c_nucleo::recibe_puntuacion(int ptos_cliente){
unsigned int puntos;

puntos_cliente=ptos_cliente;
if(servidor){
	if(ejercito != -1){
		puntos=min(MAXPUNT,puntos_cliente,ptos_locales);
		sred->nuevomensaje(puntuacionfinal(puntos));
		
		}
}


     
}



void c_nucleo::recibe_ptos_finales(int ptos){
     vector<personaje> uds;
     unsigned int pun,id;
     puntos=ptos;
     
     switch(ejercito){
                      case PATRIOTAS: uds=j.unidades_pat;
                                      break;
                      case INVASORES: uds=j.unidades_inv;
                                      break;
                                      }
                                      
     pun=puntos;
     id=0;
 while(0 < uds.size() && pun > 0){
             if(pun-uds[0].coste >= 0){                                
				 uds[0].idg=id;
				 unidades_locales.push_back(uds[0]);
                                 uds.erase(uds.begin());
                                 pun-=uds[0].coste;
                                 id++;
                                 }
                                 else pun = 0;
                                 }

     switch(ejercito){
                      case PATRIOTAS: j.unidades_pat=uds;
                                      break;
                      case INVASORES: j.unidades_inv=uds;
                                      break;
                                      }


     for(unsigned int i=0;i<unidades_locales.size();i++){
      sred->nuevomensaje(nuevaunidad2(unidades_locales[i].id,unidades_locales[i].vida,unidades_locales[i].blindaje));       
      }
      
          sred->nuevomensaje(finunidades());                                 
     
     
     }    
    



void c_nucleo::coloca_unidades()
{ //Coloca las unidades aleatoriamente en un cuadrado de 10x10
  //Si es el servidor se colocaran en la esquina inferior izquierda y si es el cliente en la superior derecha
 bool destino[10][10];
 coordenada c;
 
 for(unsigned i = 0; i < 10;i++)
  for(unsigned j = 0;j < 10;j++)
   destino[i][j] = false;
 srand(time(NULL));
 if(servidor)
 {
  for(unsigned int actual=0;actual<unidades_locales.size();actual++)
  {
   unsigned int x,y;
   do
   {
    x = rand()%10;
    y = rand()%10;

   } while(destino[x][y]);
   destino[x][y] = true;

  
c.id=actual; 
c.x=x; 
c.y=y+lista_mapas[mapa_actual].alto()-10; 
posicion_ud_locales.push_back(c);

}
 }
 else
 {
  for(unsigned int actual=0;actual<unidades_locales.size();actual++)
  {
   unsigned int x,y;
   
   do
   {
    x = rand()%10;
    y = rand()%10;
    
   } while(destino[x][y]);
   destino[x][y] = true;
  
c.id=actual; 
c.x=x+lista_mapas[mapa_actual].ancho()-10; 
c.y=y;   
posicion_ud_locales.push_back(c);

  }
 }

}


void c_nucleo::envia_posicion_unidades(){
 
 for(unsigned int i=0;i<posicion_ud_locales.size();i++){
      sred->nuevomensaje(colocarunidad(posicion_ud_locales[i].id,posicion_ud_locales[i].x,posicion_ud_locales[i].y));
}
 
     sred->nuevomensaje(fincolocarunidades());
     
     
}

void c_nucleo::recibe_remotas(int unidad,int vida,int blindaje){
     personaje p;
    
     p.vida=vida;
     p.blindaje=blindaje;
     p.id=unidad;
     p.idg=unidades_remotas.size();
     
     unidades_remotas.push_back(p);
     }                  

void c_nucleo::recibe_posicion_remotas(int unidad,int x,int y){
     coordenada c;

     c.id=unidad;
     c.x=x;
     c.y=y;
     posicion_ud_remotas.push_back(c);

     

}                   

void c_nucleo::elige_comienza_turno(){
      srand((unsigned)time(NULL));
      
      comienza=rand()%2;
      turno=comienza;
      if(comienza)
      {
       turno_pasa();
       turno = comienza;
       }
       else
     {
      for(unsigned int i = 0;i < unidades_locales.size();i++)
       movimiento_ud_locales.push_back(0);
     }
}

void c_nucleo::envia_comienza_turno(){
     int c;
      if(comienza)
      c = 0;
     else
      c = 1;
     sred->nuevomensaje(primerturno(c));
}


int c_nucleo::num_unidades(int ejercito,int num_unidad){
    vector<personaje> uds;
    int cont=0;                 
                     switch(ejercito){
                                      case PATRIOTAS: uds=j.unidades_pat;
                                                      break;
                                      case INVASORES: uds=j.unidades_inv;
                                                      break;
                                                      }
              
              for(unsigned int i=0;i<uds.size();i++){
                      if(uds[i].id == num_unidad)
                                   cont++;
                                   }
                                   
                          return cont;
                        
}                                        
                     

vector<int> c_nucleo::nuevas_uds(int ejercito){
          //Devuelve los indices de las unidades de nueva adquisición

vector<int> res;
vector<personaje> uds,uds_jug;

                    switch(ejercito){
                                     case PATRIOTAS: uds=patriotas;
                                                     uds_jug=j.unidades_pat;
                                                     break;
                                     case INVASORES: uds=invasores;
                                                     uds_jug=j.unidades_inv;
                                                     break;
                                                     }


                                                    


for(unsigned int i=0;i<uds.size();i++){ 
        if(uds[i].evolucion == -1 && uds[i].coste < j.dinero){
                     
                     res.push_back(uds[i].id);
                     }
        else if(ud_en_vector(uds[i].evolucion,uds_jug) && uds_jug[devuelve_ud(uds[i].evolucion,uds_jug)].experiencia >= 100 && uds[i].coste <= j.dinero){
                                                
                                                res.push_back(uds[i].id);
                                                
                                                }
                                                } 




return res;
}


int c_nucleo::ud_en_vector(int ud,vector<personaje> uds_jug){
    
    for(unsigned int i=0;i<uds_jug.size();i++){
            if(uds_jug[i].id == ud)
                                          return true;
                                          }
            return false;
                                          
                                          }

int c_nucleo::devuelve_ud(int ud,vector<personaje> uds_jug){
    bool encontrado=false;
    for(unsigned int i=0;i<uds_jug.size();i++){
            if(uds_jug[i].id == ud){
                                          return i;
                                          encontrado=true;
                                          }
                                          }
            if(encontrado == false){
                          return -1;
                          }
                          return -1;
                          }
                          
bool c_nucleo::esta_en_res(int ud,vector<int> res){
     bool esta=false;
     
           for(unsigned int i=0;i<res.size();i++){
                   if(res[i] == ud){
                             esta=true;
                             }
                             }
                             return esta;
                             
                             }
                             
                             
vector<personaje> c_nucleo::unidades(int ejercito){
                  switch(ejercito){
                                   case PATRIOTAS: return patriotas;
                                                   break;
                                   case INVASORES: return invasores;
                                                   break;
                                                   }
                                                   return patriotas;
                                                   }

void c_nucleo::recibe_mapa(int mapa){
     nmapa=mapa;

     coloca_unidades();
     envia_posicion_unidades();
     }

void c_nucleo::fin_pos_unidad(){
     if(!servidor){
     coloca_unidades();
     envia_posicion_unidades();
       }
	else
	sred->nuevomensaje(env_ejercito(ejercito));
     }

void c_nucleo::recibe_turno(int tturno){

turno=tturno;

      svideo->mapaelegido(lista_mapas[mapa_actual]);
      svideo->jugador_local(ejercito,unidades_locales,posicion_ud_locales);
      svideo->jugador_remoto(ejercito_enemigo,unidades_remotas,posicion_ud_remotas); 
      svideo->cambiojuego();
      ssonido->musica_principal(1);

  

     if(tturno){
                  turno_pasa();
                     }

                     }
     
void c_nucleo::fin_unidad(){
vector<personaje> uds;
unsigned int id,pun;     

if(servidor){ //Hacer selección de unidades y enviarlas
    switch(ejercito){
                      case PATRIOTAS: uds=j.unidades_pat;
                                      break;
                      case INVASORES: uds=j.unidades_inv;
                                      break;
                                      }
                                      
     pun=puntos;
     id=0;
 while(0 < uds.size() && pun > 0 && unidades_locales.size() <= 100){
             if(pun-uds[0].coste >= 0){                                
				 uds[0].idg=id;
				 unidades_locales.push_back(uds[0]);
                                 movimiento_ud_locales.push_back(uds[0].mov);
                                 uds.erase(uds.begin());
                                 pun-=uds[0].coste;
                                 id++;
                                 }
                                 else pun = 0;
                                 }

     switch(ejercito){
                      case PATRIOTAS: j.unidades_pat=uds;
                                      break;
                      case INVASORES: j.unidades_inv=uds;
                                      break;
                                      }


     for(unsigned int i=0;i<unidades_locales.size();i++){
      
      sred->nuevomensaje(nuevaunidad2(unidades_locales[i].id,unidades_locales[i].vida,unidades_locales[i].blindaje));       
      }
      
          sred->nuevomensaje(finunidades());
          svideo->elegirmapas();
				
                }
                }
                
void c_nucleo::elige_ejercito(int e){
     vector<personaje> uds;
     vector<tecnologias> tecs;
     unsigned int i=0;


//poner el ejercito que se le pasa como parametro

 ejercito=e; 


 //Calcular los puntos que tiene este ejército

	switch(ejercito){
                      case PATRIOTAS: uds=j.unidades_pat;
				      tecs=j.tecs_pat;
                                      break;
                      case INVASORES: uds=j.unidades_inv;
				      tecs=j.tecs_inv;
                                      break;
                                      }
ptos_locales=0;
	for(i=0;i<uds.size();i++)
			ptos_locales+=uds[i].coste;

	for(i=0;i<tecs.size();i++)
			ptos_locales+=tecs[i].coste;

 if(!servidor){ //Si es cliente, envía la puntuación al servidor
		
		puntos_cliente=ptos_locales;               
		sred->nuevomensaje(puntuacion(ptos_locales));
		
               }
 else{

      if(puntos_cliente != -1){ //Si ha recibido la puntuacion del cliente
               
puntos=min(MAXPUNT,puntos_cliente,ptos_locales);
sred->nuevomensaje(puntuacionfinal(puntos));

}    


}                  
}


void c_nucleo::cliente(){
     servidor=0;
     }
     
void c_nucleo::server(){
     servidor=1;
     }

     

void c_nucleo::recibe_ejercito_enemigo(int ejer){
     ejercito_enemigo=ejer;


      // PROCESADO DE UNIDADES REMOTAS
	vector<personaje> uds;
	switch(ejercito_enemigo){
			case PATRIOTAS: uds=patriotas;
					break;
			case INVASORES: uds=invasores;
					break;
				}	
	for(unsigned int i=0;i<unidades_remotas.size();i++){
	   unidades_remotas[i].im1=uds[unidades_remotas[i].id].im1;
		}
	//	   



  if(!servidor){
		sred->nuevomensaje(env_ejercito(ejercito));
                  }
	else{//Si es servidor, calcula quien comienza el turno y lo envia por red
      srand((unsigned)time(NULL));
      
      int comienza=rand()%2;
      turno=comienza; 
      sred->nuevomensaje(primerturno(turno));
      turno = !turno;
      svideo->mapaelegido(lista_mapas[mapa_actual]);
      svideo->jugador_local(ejercito,unidades_locales,posicion_ud_locales);
      svideo->jugador_remoto(ejercito_enemigo,unidades_remotas,posicion_ud_remotas); 
      svideo->cambiojuego();
      ssonido->musica_principal(1);
}

     }
     
     
void c_nucleo::turno_pasa(){ 
movimiento_ud_locales.clear();

 	 for(unsigned int i=0;i<unidades_locales.size();i++){
             movimiento_ud_locales.push_back(unidades_locales[i].mov);
             }
turno=1;
svideo->restaurar_movimiento();
             }
             
             
void c_nucleo::fin_batalla(){
     vector<personaje> uds;
     
     switch(ejercito){
                      case PATRIOTAS: uds=j.unidades_pat;
                                      break;
                      case INVASORES: uds=j.unidades_inv;
                                      break;
                                      }
     
     for(unsigned int i=0;i<unidades_locales.size();i++)
             uds.push_back(unidades_locales[i]);
             
             switch(ejercito){
                      case PATRIOTAS: j.unidades_pat=uds;
                                      break;
                      case INVASORES: j.unidades_inv=uds;
                                      break;
                                      }
                                      
     //Saber si es el ganador
     
     if(unidades_locales.empty()){ //perdedor
	svideo->fin_batalla(0);
	ssonido->fin(0);
         ganador=false;
         j.dinero+=2500;
         }
         else {//ganador
	      svideo->fin_batalla(1);
              ssonido->fin(1);     
              j.dinero+=5000;
              ganador=true;
              }
              
volcado_memoria_a_ficheros();
sred->nuevomensaje(desconectar());



}

void c_nucleo::guardar_mapa(c_mapa mapa){
	unsigned int i;
	c_mapa *temp;

//Primero paso el vector original a uno temporal

temp=(c_mapa *)malloc(sizeof(c_mapa)*num_mapas);

for(i=0;i<num_mapas;i++){
	temp[i]=lista_mapas[i];
}

//Ahora se crea el vector original con un espacio más

free(lista_mapas);
lista_mapas=(c_mapa*)malloc(sizeof(c_mapa)*(num_mapas+1));

//Ahora se vuelca el vector temporal en el original y al final se añade el nuevo mapa

for(i=0;i<num_mapas;i++){
	lista_mapas[i]=temp[i];
}
lista_mapas[num_mapas]=mapa;
num_mapas+=1;

//Salvado del mapa

mapa.salvar(mapa.nombrefichero());

//Almacenamiento en fichero de la lista de mapas

ofstream fmapas("./config/mapas.config");

fmapas << num_mapas;

for(i=0;i<num_mapas;i++){
fmapas << '\n' << lista_mapas[i].nombrefichero();
}

}

c_mapa c_nucleo::mapa(char * md5){
c_mapa aux;
	
	for(unsigned int i=0;i<num_mapas;i++){
		if(strcmp(lista_mapas[i].md5(),md5) == 0)
			aux=lista_mapas[i];
}
return aux;
}
  

bool compare(char * a,char * b)
{
 if(strlen(a ) != strlen(b ))
  return false;
 
 int l = strlen(a );
 
 for(int i = 0;i < l; i++)
  if(a[i] != b[i])
   return false;

 return true;
}


void c_nucleo::borra_mapa(char * md5){
c_mapa aux;
unsigned int i;

	for(i=0;i<num_mapas;i++){
		if(compare(lista_mapas[i].md5(),md5)){
			if(i == num_mapas-1){
				num_mapas-=1;
				}
			else{			
			aux=lista_mapas[num_mapas-1];
			lista_mapas[i]=aux;
			num_mapas-=1;
			}
}
}

ofstream fmapas("./config/mapas.config");

fmapas << num_mapas;

for(i=0;i<num_mapas;i++){
fmapas << '\n' << lista_mapas[i].nombrefichero();
}


}

void c_nucleo::carga_mapas(){
	
	ifstream datos("./config/mapas.config");
	c_mapa map;
        
	string bufer; // Para leer cada linea
	char ruta[30];

	datos >> num_mapas;
	getline(datos,bufer); // para desechar la primera linea
	
	lista_mapas=(c_mapa*)malloc(sizeof(c_mapa)*num_mapas);	

	for(unsigned int i=0;i<num_mapas;i++){

	getline(datos,bufer);
	//Creamos un flujo en memoria sobre bufer
	istringstream linea(bufer);
	//Se leen los componentes de la linea 
	linea >> ruta;
	map.cargar(ruta);
	lista_mapas[i]=map;
	map.destruir();
}
}
     

void c_nucleo::mapa_aleatorio(){
     srand((unsigned)time(NULL));	     

     mapa_actual=rand()%num_mapas;
     
     svideo->mapaelegido(lista_mapas[mapa_actual]);
     sred->nuevomensaje(emapa(lista_mapas[mapa_actual].md5()));


}


void c_nucleo::mapa_elegido(char * md5){

	for(unsigned int i=0;i<num_mapas;i++){
		if(compare(lista_mapas[i].md5(),md5)){
                   mapa_actual=i;
		   svideo->mapaelegido(lista_mapas[i]);	
		   sred->nuevomensaje(emapa(lista_mapas[i].md5()));
		   break;
			}
		}
}


void c_nucleo::existe_mapa(char * md5){
	bool esta=false;	
	
	for(unsigned int i=0;i<num_mapas;i++){
		if(compare(lista_mapas[i].md5(),md5)){
                    esta=true;
		    mapa_actual=i; 
			}
		}
	if(esta)	
	sred->nuevomensaje(tengomapa(1));
	else
	sred->nuevomensaje(tengomapa(0));

}


void c_nucleo::envia_mapa_elegido(int elec){
	
	if(elec == 0){
		sred->nuevomensaje(enviar_mapa(lista_mapas[mapa_actual]));			
 }    

coloca_unidades();
envia_posicion_unidades();
}


void c_nucleo::fin_mapa(c_mapa m){
	guardar_mapa(m);
	
	for(unsigned int i=0;i<num_mapas;i++){
		if(compare(m.md5(),lista_mapas[i].md5())){
		   mapa_actual=i; 
		   svideo->mapaelegido(lista_mapas[mapa_actual]);
}
}

}


int c_nucleo::absolut(int n){
	if(n < 0){
		return -n;
		}
	else
		return n;
}






int c_nucleo::ataque_local(int idgl,int idgr){
	srand((unsigned)time(NULL));
        personaje aux;
        unsigned int danio;
        bool turno_acabado=true;
	coordenada c;
	float distancia;
	

distancia=(sqrt(absolut((posicion_ud_locales[idgl].x-posicion_ud_remotas[idgr].x)*(posicion_ud_locales[idgl].x-posicion_ud_remotas[idgr].x)) + absolut((posicion_ud_locales[idgl].y-posicion_ud_remotas[idgr].y)*(posicion_ud_locales[idgl].y-posicion_ud_remotas[idgr].y))));

ssonido->sonido_atacando(unidades_locales[pos_id(idgl,posicion_ud_locales)]);


	if(movimiento_ud_locales[pos_id(idgl,posicion_ud_locales)] > 0 && distancia <= unidades_locales[idgl].alcance_ataque ){ 

		danio=rand()%unidades_locales[pos_id(idgl,posicion_ud_locales)].danio_ataque;
                if(danio == 0) { danio = 1; }
		unidades_locales[pos_id(idgl,posicion_ud_locales)].experiencia+=danio;
		unidades_remotas[pos_id(idgr,posicion_ud_remotas)].vida-=danio;
		movimiento_ud_locales[pos_id(idgl,posicion_ud_locales)]=0;
		ssonido->sonido_ataque(unidades_locales[pos_id(idgl,posicion_ud_locales)]);		
		sred->nuevomensaje(ataque(idgr,danio));
	if(muerto(unidades_remotas[pos_id(idgr,posicion_ud_remotas)])){ 
	      unidades_locales[pos_id(idgl,posicion_ud_locales)].experiencia+=2*danio;
	      svideo->elimina_unidad_remota(idgr); 
              
	unsigned int p=pos_id(idgr,posicion_ud_remotas);
	if(p != unidades_remotas.size()-1){
	      aux=unidades_remotas[unidades_remotas.size()-1];
              unidades_remotas[p]=aux;
              unidades_remotas.pop_back();
	      c=posicion_ud_remotas[posicion_ud_remotas.size()-1];
	      posicion_ud_remotas[p]=c;
	      posicion_ud_remotas.pop_back();
	      
	      		
		}
		else{
			unidades_remotas.pop_back();
			posicion_ud_remotas.pop_back();
			}
              
              
 
//Comprobar que se ha acabado la batalla

if(unidades_locales.size() == 0 || unidades_remotas.size() == 0)
	fin_batalla();              
              
              }
                  
     //Comprobar que se ha acabado el turno
     for(unsigned int i=0;i<movimiento_ud_locales.size();i++)
             if(movimiento_ud_locales[i] != 0){
                turno_acabado=false;
}
                           
     if(turno_acabado){
                      sred->nuevomensaje(pasa_turno());              
                      turno = 0;
                   }
	
return danio;
}
else 
	return 0;
}
	



void c_nucleo::movimiento_local(int idgl,int x,int y,int movimientorestante){
bool turno_acabado=true;

ssonido->sonido_mov(unidades_locales[idgl]);

	posicion_ud_locales[idgl].x=x;
	posicion_ud_locales[idgl].y=y; 
	movimiento_ud_locales[idgl]=movimientorestante; 


sred->nuevomensaje(movimiento(idgl,x,y));

     //Comprobar que se ha acabado el turno
     for(unsigned int i=0;i<movimiento_ud_locales.size();i++)
             if(movimiento_ud_locales[i] != 0)
                turno_acabado=false;
                           
     if(turno_acabado){
                      sred->nuevomensaje(pasa_turno());              
                      turno = 0;
}
}

void c_nucleo::ataque_remoto(int idgl, int dano){
		
	svideo->ataque_remoto(idgl,dano);
	unidades_locales[pos_id(idgl,posicion_ud_locales)].vida-=dano;
	ssonido->sonido_ataque_r();
	
	if(muerto(unidades_locales[pos_id(idgl,posicion_ud_locales)])){
		svideo->elimina_unidad_local(idgl);
		
		unidades_locales[pos_id(idgl,posicion_ud_locales)]=unidades_locales[unidades_locales.size()-1];
		unidades_locales.pop_back();
		movimiento_ud_locales[pos_id(idgl,posicion_ud_locales)]=movimiento_ud_locales[movimiento_ud_locales.size()-1];
		movimiento_ud_locales.pop_back();	
		posicion_ud_locales[pos_id(idgl,posicion_ud_locales)]=posicion_ud_locales[posicion_ud_locales.size()-1];
		posicion_ud_locales.pop_back();

if(unidades_locales.size() == 0 || unidades_remotas.size() == 0)
	fin_batalla(); 
		

}
}


void c_nucleo::movimiento_remoto(int idgr,int x, int y){

	posicion_ud_remotas[idgr].x=x;
	posicion_ud_remotas[idgr].y=y;

	svideo->movimiento_remoto(idgr,x,y);

}


void c_nucleo::termina_turno(){

	turno=!turno;
	sred->nuevomensaje(pasa_turno());

}

int c_nucleo::pos_id(unsigned int idg,vector<coordenada> locales){
	unsigned int posicion;

	for(unsigned int i=0;i<locales.size();i++){
		if(locales[i].id == idg){
			posicion=i;
			break;
			}
}
return posicion;
}



int c_nucleo::vida(unsigned int idg,unsigned int ejercito){
// ejercito: 0 local  1 remoto
	vector<personaje> uds;
	vector<coordenada> pos;
		
		switch(ejercito){
			case 0: uds=unidades_locales;
				pos=posicion_ud_locales;
				break;
			case 1: uds=unidades_remotas;
				pos=posicion_ud_remotas;
				break;
				}
	
	return uds[pos_id(idg,pos)].vida;

}




void c_nucleo::bucle()
{
 bool continuarejecucion = true;
 while(continuarejecucion)
 {
  tiempo = SDL_GetTicks();
  bool revisarcola = true;
  c_evento ev(E_TERMINARCICLO);
  eventos.push(ev);
  while(revisarcola)
  {
   ev = eventos.front();
   eventos.pop();
   switch(ev.event)
   {
    case E_TERMINARCICLO: revisarcola = false; break;
    case E_QUIT: revisarcola = false; continuarejecucion = false; break;
    case E_MOVRATON: mousex = ev.vector[0]; mousey = ev.vector[1]; break;
   }
  } 

 
  sentrada->ciclo();
  svideo->ciclo();
  ssonido->ciclo();
  
if(sred->conectado())
   sred->ciclo();

  else
   if(sred->conectando())
    sred->comprobarestadoconexion();
  if((SDL_GetTicks() - tiempo) < 25)
   SDL_Delay(25 - (SDL_GetTicks() - tiempo));
 }
}

void c_nucleo::nuevo_evento(c_evento ev)
{
 eventos.push(ev);
}



 


     
